package cn.zb.common.aop;

import cn.zb.common.annotation.Dict;
import cn.zb.common.util.RedisUtil;
import cn.zb.common.util.Result;
import cn.zb.common.vo.DictItemVO;
import cn.zb.common.vo.DictVO;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.SneakyThrows;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * 字典切面类查询实现
 *
 * @author: 刚哥
 * @date: 2024-11-29 12:48
 **/
@Aspect
@Component
public class DictAspect {

    // 添加了@DictQuery注解的控制器方法才查询字典
    @Around("@annotation(cn.zb.common.annotation.DictQuery)")
    public Object around(ProceedingJoinPoint jp) throws Throwable {
        // 执行控制器方法获取到控制器的返回值
        Object obj = jp.proceed();
        // 判断是否为Result类型
        if(obj instanceof Result){
            Result result = (Result) obj;
            parseDict(result);
        }
        return obj;
    }

    public void parseDict(Result result){
        // 获取到数据
        Object data = result.getData();
        if(data instanceof IPage){ // 数据是分页对象时
            List<JSONObject> json = new ArrayList<>();
            IPage page = (IPage) data;
            page.getRecords().forEach(o->{
                JSONObject jsonObject = setField(o);
                json.add(jsonObject);
            });
            ((IPage)data).setRecords(json);
            result.setData(data);
        }else if(data instanceof List){ // 判断数据是集合时
            List<JSONObject> json = new ArrayList<>();
            List list = (List) data;
            list.forEach(o->{
                JSONObject jsonObject = setField(o);
                json.add(jsonObject);
            });
            result.setData(json);
        }else{ // 数据是对象时
            result.setData(setField(data));
        }
    }

    @SneakyThrows
    public JSONObject setField(Object obj){
        // 获取redis中的所有字典数据
        List<DictVO> dictVOS = (List<DictVO>) redisUtil.get("dict");
        JSONObject json = new JSONObject();
        // 遍历对象中所有的属性
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);// 暴力访问
            // 判断属性是否使用了字典注解
            Dict dict = field.getAnnotation(Dict.class);
            if(dict != null){
                // 如果未设置字典值 就跳过该属性不设置
                Object value = field.get(obj);
                if(value == null) {
                    json.put(field.getName(),field.get(obj));
                    continue;
                }
                // 取出字典真实数据
                DictVO dictVO = dictVOS.stream()
                        .filter(vo -> vo.getDictType().equals(dict.dictCode()))
                        .findFirst().get();
                DictItemVO dictItemVO = dictVO.getItems().stream()
                        .filter(vo -> vo.getDictValue().equals(value)).findFirst().get();
                json.put(field.getName()+"Dict",dictItemVO.getDictLabel());
            }
            // 每个属性 无论是否使用字典 都将原数据存储
            json.put(field.getName(),field.get(obj));
        }
        return json;
    }

    @Resource
    RedisUtil redisUtil;
}
